
#include <xc.h>

#include <mem_sst25vf064c.h>
#include <system.h>
#include <libpic30.h>

unsigned char pcache[256];
unsigned int cacheptr;     // current position to write to into the cache

unsigned long pageptr;      // current page to write to the flash

//#define D 100

unsigned long findmem() {
   unsigned char data;
   unsigned long low = 0;
   unsigned long step = 65536*128 / 2;

   unsigned long p;

   do {
      p = low + step;
      readmem(p, &data, 1);

      if(data!=255) low = p;

      if(step == 256) return low;

      step = step / 2;

    } while(1);
}

void writepage(unsigned long addr) {

    // write 256 bytes from pcache to memory
    // caller must make sure that address is aligned with 256 byte boundary (last byte is 0)
    
        unsigned char b;
        int i=0;
        unsigned char *p;

        p = (unsigned char *)(&addr);

        __delay_us(D);
        MEM_CS = 1;
        __delay_us(D);

        MEM_CS = 0;
        __delay_us(D);

        SPI1BUF = 0x02;
        while(SPI1STATbits.SPIRBF==0);
        b = SPI1BUF;

        SPI1BUF = p[2];
        while(SPI1STATbits.SPIRBF==0);
        b = SPI1BUF;

        SPI1BUF = p[1];
        while(SPI1STATbits.SPIRBF==0);
        b = SPI1BUF;

        SPI1BUF = p[0];
        while(SPI1STATbits.SPIRBF==0);
        b = SPI1BUF;

        for(i = 0; i<256; i++) {
           SPI1BUF = pcache[i];
           while(SPI1STATbits.SPIRBF==0);
           b = SPI1BUF;
        }

        __delay_us(D);
        MEM_CS = 1;

}

void readmem(unsigned long addr, unsigned char* data, int n) {
        unsigned char b;
        int i=0;
        unsigned char *p;

        p = (unsigned char *)(&addr);

        __delay_us(D);
        MEM_CS = 1;
        __delay_us(D);

        MEM_CS = 0;
        __delay_us(D);

        //LED_Toggle(LED_TEST);

        SPI1BUF = 0x03;
        while(SPI1STATbits.SPIRBF==0);
        b = SPI1BUF;

        SPI1BUF = p[2];
        while(SPI1STATbits.SPIRBF==0);
        b = SPI1BUF;

        SPI1BUF = p[1];
        while(SPI1STATbits.SPIRBF==0);
        b = SPI1BUF;

        SPI1BUF = p[0];
        while(SPI1STATbits.SPIRBF==0);
        b = SPI1BUF;

        for(i = 0; i<n; i++) {
           SPI1BUF = 0;
           while(SPI1STATbits.SPIRBF==0);
           b = SPI1BUF;

           data[i] = b;
        }

        __delay_us(D);
        MEM_CS = 1;
}

unsigned char getmemid() {
        unsigned char b;

        int n=50;

        __delay_us(D);
        MEM_CS = 1;
        __delay_us(D);

        MEM_CS = 0;
        __delay_us(D);

         SPI1BUF = 0x90;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;

         SPI1BUF = 0;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;

         SPI1BUF = 0;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;

         SPI1BUF = 0;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;

         SPI1BUF = 0;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;


        __delay_us(D);
        MEM_CS = 1;

        return b;
}

void writeenable() {
        unsigned char b;

        int n=50;

        __delay_us(D);
        MEM_CS = 1;
        __delay_us(D);

        MEM_CS = 0;
        __delay_us(D);

         SPI1BUF = 0x06;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;

        __delay_us(D);
        MEM_CS = 1;

}

int waitbusy() {
    int waited = false;
    while(readstatus()&0x01 == 0x01) {
        __delay_us(100);
        waited = true;
    }

    return waited;
}

unsigned char readstatus() {
        unsigned char b;

        int n=50;

        __delay_us(D);
        MEM_CS = 1;
        __delay_us(D);

        MEM_CS = 0;
        __delay_us(D);

         SPI1BUF = 0x05;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;

         SPI1BUF = 0;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;


        __delay_us(D);
        MEM_CS = 1;

        return b;
}

void clearblockprotection() {
        unsigned char b;

        int n=50;

        __delay_us(D);
        MEM_CS = 1;
        __delay_us(D);

        MEM_CS = 0;
        __delay_us(D);

         SPI1BUF = 0x50;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;

        __delay_us(D);
        MEM_CS = 1;
        __delay_us(D);
        MEM_CS = 0;
        __delay_us(D);

         SPI1BUF = 0x01;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;

         SPI1BUF = 0;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;


        __delay_us(D);
        MEM_CS = 1;

}

void erase() {
        unsigned char b;

        int n=50;

        __delay_us(D);
        MEM_CS = 1;
        __delay_us(D);

        MEM_CS = 0;
        __delay_us(D);

         SPI1BUF = 0x60;
         while(SPI1STATbits.SPIRBF==0);
         b = SPI1BUF;

        __delay_us(D);
        MEM_CS = 1;

        while(readstatus()&0x01 == 0);
}
